//==================================================================================================
/**
  EVE - Expressive Vector Engine
  Copyright : EVE Project Contributors
  SPDX-License-Identifier: BSL-1.0
**/
//==================================================================================================
#include "test.hpp"

#include <eve/module/core.hpp>
#include <eve/module/math.hpp>

#include <cmath>

//==================================================================================================
// Types tests
//==================================================================================================
TTS_CASE_TPL("Check return types of sinh", eve::test::simd::ieee_reals)
<typename T>(tts::type<T>)
{
  using v_t = eve::element_type_t<T>;

  TTS_EXPR_IS(eve::sinh(T()), T);
  TTS_EXPR_IS(eve::sinh(v_t()), v_t);
};

//==================================================================================================
// sinh  tests
//==================================================================================================
auto maxi = []<typename T>(eve::as<T> const&)
{
  using v_t = eve::element_type_t<T>;
  v_t ovl   = eve::ieee_constant<0x1.62e42fefa39efp+9, 0x1.6181480p+6f>(eve::as<v_t>{}); // 709.782712893384// 88.376251220703125f,
  return T(ovl);
};

auto mini = []<typename T>(eve::as<T> const& tgt) { return -maxi(tgt); };

TTS_CASE_WITH("Check behavior of sinh on wide",
              eve::test::simd::ieee_reals,
              tts::generate(tts::randoms(tts::constant(mini), tts::constant(maxi)),
                            tts::randoms(-1.0, 1.0)))
<typename T>(T const& a0, T const& a1)
{
  using v_t = eve::element_type_t<T>;
  using eve::cosh;
  using eve::sinh;

  TTS_ULP_EQUAL(sinh(a0), tts::map([](auto e) -> v_t { return std::sinh(e); }, a0), 2);
  TTS_ULP_EQUAL(sinh(a1), tts::map([](auto e) -> v_t { return std::sinh(e); }, a1), 2);

  TTS_ULP_EQUAL(eve::sinh(eve::inf(eve::as<v_t>())), eve::inf(eve::as<v_t>()), 0.5);
  TTS_ULP_EQUAL(eve::sinh(eve::minf(eve::as<v_t>())), eve::minf(eve::as<v_t>()), 0.5);
  TTS_ULP_EQUAL(eve::sinh(eve::zero(eve::as<v_t>())), eve::zero(eve::as<v_t>()), 0.5);
  TTS_ULP_EQUAL(eve::sinh(eve::mzero(eve::as<v_t>())), eve::mzero(eve::as<v_t>()), 0.5);
  TTS_ULP_EQUAL(eve::sinh(eve::nan(eve::as<v_t>())), eve::nan(eve::as<v_t>()), 0.5);

};


//==================================================================================================
// Tests for masked sinh
//==================================================================================================
TTS_CASE_WITH("Check behavior of eve::masked(eve::sinh)(eve::wide)",
              eve::test::simd::ieee_reals,
              tts::generate(tts::randoms(eve::valmin, eve::valmax),
              tts::logicals(0, 3)))
<typename T, typename M>(T const& a0,
                         M const& mask)
{
  TTS_IEEE_EQUAL(eve::sinh[mask](a0),
            eve::if_else(mask, eve::sinh(a0), a0));
};
